package com.wcbtest.docker.util;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSONObject;
import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.command.ListVolumesResponse;
import com.github.dockerjava.api.model.*;
import com.github.dockerjava.core.DefaultDockerClientConfig;
import com.github.dockerjava.core.DockerClientBuilder;
import com.github.dockerjava.core.command.LogContainerResultCallback;
import com.github.dockerjava.httpclient5.ApacheDockerHttpClient;
import com.wcbtest.docker.domain.MachineDockerInfo;
import com.wcbtest.docker.domain.dto.*;
import com.wcbtest.docker.enums.ServiceTypeEnum;
import org.apache.commons.lang3.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

public class DockerClientUtils {

    private DockerClient client;


    /**
     * 使用测试
     * @param args
     */
    public static void main(String[] args) {
        //Docker-Java 的方法命名和结构设计通常遵循以下原则：
        //Docker API 端点	Docker-Java 对应方法	示例
        //GET /containers/json	dockerClient.listContainersCmd().exec()	获取容器列表
        //POST /containers/create	dockerClient.createContainerCmd(image)	创建容器
        //POST /containers/{id}/start	dockerClient.startContainerCmd(id).exec()	启动容器
        //DELETE /containers/{id}	dockerClient.removeContainerCmd(id).exec()	删除容器
        //GET /images/json	dockerClient.listImagesCmd().exec()	获取镜像列表
        //POST /images/create	dockerClient.pullImageCmd(image).exec()	拉取镜像
        // 初始化Docker客户端
        //DockerClient dockerClient = DockerClientUtilsNew.initDockerClient("tcp://192.168.110.130:2375");
        //// 获取容器列表
        //List<Container> exec = dockerClient.listContainersCmd().exec();
        //System.out.println(exec);
        MachineDockerInfo machineDockerInfo = new MachineDockerInfo();
        machineDockerInfo.setHost("tcp://192.168.110.130:2375");
        DockerClientUtils docker = new DockerClientUtils(machineDockerInfo);
        System.out.println("初始化Docker连接");
        System.out.println(JSONObject.toJSONString(docker));

        DockerContainerNumDTO info = docker.getDockerInfo();
        System.out.println("获取Docker系统信息");
        System.out.println(JSONObject.toJSONString(info));

        List<DockerContainerInfoDTO> allContainer = docker.getAllContainer();
        System.out.println("获取所有容器(运行中和已停止)");
        System.out.println(JSONObject.toJSONString(allContainer));
    }


    /**
     * 构造函数，初始化Docker连接
     */
    public DockerClientUtils(MachineDockerInfo machineDockerInfo) {
        String dockerHost = machineDockerInfo.getHost();
        System.out.println("连接信息："+ dockerHost);
        /**
         * 第一种方式：这种方式也可以
         */
        //// 配置 Docker 连接
        //DefaultDockerClientConfig config = DefaultDockerClientConfig.createDefaultConfigBuilder()
        //        .withDockerHost(dockerHost)  // ✅ 正确路径
        //        .build();
        //// 创建 Docker 客户端
        //DockerClient build = DockerClientBuilder.getInstance(config)
        //        .build();


        /**
         * 第二种方式：需要docker-java-transport-httpclient5
         */

        // 配置 Docker 连接
        DefaultDockerClientConfig config = DefaultDockerClientConfig.createDefaultConfigBuilder()
                .withDockerHost(dockerHost)  // ✅ 正确路径
                .build();
        // 创建 HTTP 客户端（关键：避免警告）
        ApacheDockerHttpClient httpClient = new ApacheDockerHttpClient.Builder()
                .dockerHost(config.getDockerHost())
                .build();
        // 创建 Docker 客户端
        DockerClient build = DockerClientBuilder.getInstance(config)
                .withDockerHttpClient(httpClient)  // ✅ 显式配置
                .build();
        this.client = build;
    }


    /**
     * 获取Docker系统信息
     */
    public DockerContainerNumDTO getDockerInfo() {
        Info info = client.infoCmd().exec();
        DockerContainerNumDTO dto = new DockerContainerNumDTO();
        dto.setAllContainer(info.getContainers());
        dto.setStopContainer(info.getContainersStopped());
        dto.setRunningContainer(info.getContainersRunning());
        return dto;
    }

    /**
     * 获取Docker系统信息
     */
    public Version getVersion() {
        Version exec = client.versionCmd().exec();
        return exec;
    }

    /**
     * 启动容器
     */
    public void startContainer(String containerId) {
        if (!isContainerRunning(containerId)) {
            client.startContainerCmd(containerId).exec();
        }
    }

    /**
     * 停止容器
     */
    public void stopContainer(String containerId) {
        if (isContainerRunning(containerId)) {
            client.stopContainerCmd(containerId).exec();
        }
    }

    /**
     * 重启容器
     *
     * @param containerId
     */
    public void restartContainer(String containerId) {
        client.restartContainerCmd(containerId).exec();
    }

    /**
     * 获取所有容器(运行中和已停止)
     */
    public List<DockerContainerInfoDTO> getAllContainer() {
        List<DockerContainerInfoDTO> result = new ArrayList<>();
        result.addAll(getRunningContainer());
        result.addAll(getStopContainer());
        return result;
    }

    /**
     * 获取运行中的容器
     */
    public List<DockerContainerInfoDTO> getRunningContainer() {
        return convertContainers(client.listContainersCmd().exec(), true);
    }

    /**
     * 获取已停止的容器
     */
    public List<DockerContainerInfoDTO> getStopContainer() {
        return convertContainers(
                client.listContainersCmd()
                        .withShowAll(true)
                        .withStatusFilter(Collections.singleton("exited"))
                        .exec(),
                false
        );
    }

    /**
     * 获取容器日志,默认显示1000行
     */
    public List<String> getContainerLogs(String containerId, Integer lineCount) {
        List<String> logs = new ArrayList<>();
        try {
            if (lineCount == null || lineCount < 1) {
                lineCount = 1000;
            }
            client.logContainerCmd(containerId)
                    .withStdOut(true)
                    .withStdErr(true)
                    .withTail(lineCount)
                    .exec(new LogContainerResultCallback() {
                        @Override
                        public void onNext(Frame item) {
                            logs.add(item.toString());
                        }
                    }).awaitCompletion();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return logs;
    }

    /**
     * 根据条件筛选容器
     */
    public List<DockerContainerInfoDTO> filterContainers(DockerContainerInfoDTO dockerContainerInfoDTO) {
        return getAllContainer().stream()
                .filter(c -> dockerContainerInfoDTO.getId() == null || c.getId().contains(dockerContainerInfoDTO.getId()))
                .filter(c -> dockerContainerInfoDTO.getName() == null || c.getName().contains(dockerContainerInfoDTO.getName()))
                .filter(c -> dockerContainerInfoDTO.getImage() == null || c.getName().contains(dockerContainerInfoDTO.getImage()))
                .filter(c -> dockerContainerInfoDTO.getStatus() == null || Objects.equals(c.getStatus(), dockerContainerInfoDTO.getStatus()))
                .filter(c -> dockerContainerInfoDTO.getIsDockerCompose() == null || Objects.equals(c.getIsDockerCompose(), dockerContainerInfoDTO.getIsDockerCompose()))
                .collect(Collectors.toList());
    }

    // 辅助方法：转换Container对象为ContainerInfoDTO
    private List<DockerContainerInfoDTO> convertContainers(List<Container> containers, boolean status) {
        List<DockerContainerInfoDTO> result = new ArrayList<>();
        containers.forEach(container -> {
            DockerContainerInfoDTO dto = new DockerContainerInfoDTO();
            dto.setId(StringUtils.substring(container.getId(), 0, 12));
            dto.setName(container.getNames()[0]);
            //dto.setName(container.getNames()[0].substring(1));
            dto.setImage(container.getImage());
            dto.setStatus(status);
            if (container.getLabels() != null) {
                dto.setDesc(container.getLabels().get("DESC"));
                String type = container.getLabels().get("TYPE");
                if (type != null) {
                    dto.setType(ServiceTypeEnum.valueOf(type));
                }
            }
            ContainerPort[] ports = container.getPorts();
            ArrayList<String> portssto = new ArrayList<>();
            for (ContainerPort port : ports) {
                if (Objects.equals("0.0.0.0", port.getIp())) {
                    portssto.add(port.getType() + " " + port.getPublicPort() + "/" + port.getPrivatePort());
                }
            }
            dto.setPorts(portssto);
            dto.setLabels(container.getLabels());
            dto.setCommand(container.getCommand());
            dto.setMounts(container.getMounts());
            dto.setCreated(container.getCreated());

            String containerService = getContainerLabel(container, "com.docker.compose.service");
            dto.setIsDockerCompose(StringUtils.isNoneBlank(containerService));
            result.add(dto);
        });

        return result;
    }

    // 辅助方法：检查容器是否在运行
    private boolean isContainerRunning(String containerId) {
        return getRunningContainer().stream()
                .anyMatch(c -> c.getId().equals(containerId));
    }

    public List<DockerImageInfoDTO> dockerImagesList(DockerImageInfoDTO dockerImageInfoDTO) {
        List<Image> exec = client.listImagesCmd().exec();
        List<DockerImageInfoDTO> collect = exec.stream().map(e -> {
            DockerImageInfoDTO dto = BeanUtil.copyProperties(e, DockerImageInfoDTO.class);
            dto.setId(dto.getId().substring(7, 19));
            return dto;
        }).collect(Collectors.toList());
        return collect;
    }

    /**
     * 获取容器标签
     */
    private String getContainerLabel(Container container, String labelKey) {
        if (container.getLabels() != null) {
            return container.getLabels().get(labelKey);
        }
        return null;
    }

    public List<Map> dockerVolumeList(DockerVolumeInfoDTO dockerVolumeInfoDTO) {
        ListVolumesResponse exec = client.listVolumesCmd().exec();
        List<Map> volumes = (List<Map>) exec.getRawValues().get("Volumes");
        ////List<InspectVolumeResponse> volumes = exec.getVolumes();
        //List<DockerVolumeInfoDTO> collect = volumes.stream().map(e -> {
        //    DockerVolumeInfoDTO dto = new DockerVolumeInfoDTO();
        //    dto.setCreatedAt((String) e.get("CreatedAt"));
        //    dto.setDriver((String) e.get("Driver"));
        //    dto.setLabels((List<String>) e.get("Labels"));
        //    dto.setMountpoint((String) e.get("Mountpoint"));
        //    dto.setName((String) e.get("Name"));
        //    dto.setOptions((String) e.get("Options"));
        //    dto.setScope((String) e.get("Scope"));
        //    //DockerVolumeInfoDTO dto = BeanUtil.copyProperties(e, DockerVolumeInfoDTO.class);
        //    return dto;
        //}).collect(Collectors.toList());
        return volumes;
    }

    public List<DockerNetworkInfoDTO> dockerNetworkList(DockerNetworkInfoDTO dockerNetworkInfoDTO) {
        List<Network> exec = client.listNetworksCmd().exec();
        List<DockerNetworkInfoDTO> collect = exec.stream().map(e -> {
            DockerNetworkInfoDTO dto = BeanUtil.copyProperties(e, DockerNetworkInfoDTO.class);
            return dto;
        }).collect(Collectors.toList());
        return collect;
    }
}
